home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / BlueBox Spy / Blue Box Daemon / source / CSimpleTCPServer.cp < prev    next >
Encoding:
Text File  |  1998-08-10  |  8.7 KB  |  305 lines  |  [TEXT/CWIE]

  1. // ===========================================================================
  2. //    CSimpleTCPServer.cp            ©1995-1998 Metrowerks Inc. All rights reserved.
  3. // ===========================================================================
  4. //    Servers are endpoints that watch and wait for connection requests from
  5. //    remote clients. The actual connection to and interaction with remote clients
  6. //    is handled by the "responders."
  7.  
  8. #include "CSimpleTCPServer.h"
  9.  
  10. #include <UNetworkFactory.h>
  11. #include <LWindow.h>
  12. #include <LApplication.h>
  13. #include <UMemoryMgr.h>
  14.  
  15. #include <Sound.h>
  16.  
  17.  
  18. // ===========================================================================
  19. //        • Resource IDs
  20. // ===========================================================================
  21.  
  22. const PP_PowerPlant::ResIDT        PPob_WaitIngWindow    = 131;
  23. const PP_PowerPlant::PaneIDT    pPort                = 'PORT';
  24. const PP_PowerPlant::PaneIDT    pAddress            = 'ADDR';
  25. const PP_PowerPlant::PaneIDT    pMaxConnection        = 'MCON';
  26. const PP_PowerPlant::PaneIDT    pCurrConnection        = 'CCON';
  27. const PP_PowerPlant::PaneIDT    pRejectedConnection    = 'RCON';
  28.  
  29. // ---------------------------------------------------------------------------
  30. //        • CSimpleTCPServer
  31. // ---------------------------------------------------------------------------
  32.  
  33. CSimpleTCPServer::CSimpleTCPServer(
  34.         LCommander* inSuper)
  35.         : LSingleDoc(inSuper)
  36. {
  37.     mWindow = nil;
  38.     mEndpoint = nil;
  39.     mServerThread = nil;
  40.     mQuitWhenDone = false;
  41.     mSaveOption = 0;
  42. }
  43.  
  44. // ---------------------------------------------------------------------------
  45. //        • ~CSimpleTCPServer
  46. // ---------------------------------------------------------------------------
  47.  
  48. CSimpleTCPServer::~CSimpleTCPServer()
  49. {
  50.     if (mEndpoint) {
  51.         mEndpoint->RemoveListener(this);
  52.         delete mEndpoint;
  53.         mEndpoint = nil;
  54.     }
  55.  
  56.     if (mServerThread)
  57.         mServerThread->DeleteThread();
  58. }
  59.  
  60. // ---------------------------------------------------------------------------
  61. //        • ListenToMessage
  62. // ---------------------------------------------------------------------------
  63.  
  64. void
  65. CSimpleTCPServer::ListenToMessage(
  66.                             PP_PowerPlant::MessageT        inMessage,
  67.                             void *                    /* ioParam */)
  68. {
  69.     switch (inMessage) {
  70.         case T_LISTEN:
  71.             if (mServerThread) {
  72.                 mServerThread->ResumeServerThread();
  73.             }
  74.             break;
  75.     }
  76. }
  77.  
  78. // ---------------------------------------------------------------------------
  79. //        • WaitForConnections
  80. // ---------------------------------------------------------------------------
  81. //    Wait for connection(s) from remote machine(s) using the parameters that have
  82. //    been passed to us. The connection information window is also opened at this time.
  83. //
  84. //    This routine creates an endpoint and a thread for the server process.
  85. //    When the thread runs, it will bind the endpoint and wait for T_Listen events.
  86. //    Responses to T_Listens will be handled on NEW endpoints. This endpoint ONLY listens.
  87.  
  88. void
  89. CSimpleTCPServer::WaitForConnections(
  90.     UInt32        inListenQueueSize,
  91.     UInt32        inPort)
  92. {
  93.     mConnectionCount = mRejectionCount = 0;
  94.  
  95.     CreateServerWindow(inListenQueueSize, inPort);
  96.     
  97.     mEndpoint = PP_PowerPlant::UNetworkFactory::CreateTCPEndpoint();
  98.     mEndpoint->AddListener(this);
  99.  
  100.     mServerThread = new CTCPServerThread(
  101.                             inListenQueueSize,
  102.                             inPort,
  103.                             mEndpoint,
  104.                             this);
  105.  
  106.     mServerThread->Resume();
  107. }
  108.  
  109.  
  110. // ---------------------------------------------------------------------------
  111. //        • IsIdle
  112. // ---------------------------------------------------------------------------
  113.  
  114. Boolean
  115. CSimpleTCPServer::IsIdle()
  116. {
  117.     if (mEndpoint == nil) {
  118.         return true;
  119.     }
  120.     
  121.     PP_PowerPlant::EEndpointState netState = mEndpoint->GetState();
  122.     return ((netState == PP_PowerPlant::endpoint_Idle) || (netState == PP_PowerPlant::endpoint_Unbound));
  123. }
  124.  
  125.  
  126. // ---------------------------------------------------------------------------
  127. //        • ServerThreadDied
  128. // ---------------------------------------------------------------------------
  129.  
  130. void
  131. CSimpleTCPServer::ServerThreadDied()
  132. {
  133.     mServerThread = nil;
  134.  
  135.     //Re-issue the quit command when we are ready.
  136.     if (mQuitWhenDone) {
  137.         PP_PowerPlant::LApplication* theApp = dynamic_cast<PP_PowerPlant::LApplication*>(GetSuperCommander());
  138.         if ( theApp ) {
  139.             theApp->DoQuit(mSaveOption);
  140.         }
  141.     }
  142.  
  143.     delete this;
  144. }
  145.  
  146. // ---------------------------------------------------------------------------
  147. //        • Disconnect
  148. // ---------------------------------------------------------------------------
  149.  
  150. void
  151. CSimpleTCPServer::Disconnect()
  152. {
  153.     if (mServerThread) {
  154.         mServerThread->StartDisconnect();
  155.     }
  156. }
  157.  
  158. PP_PowerPlant::LTCPEndpoint*
  159. CSimpleTCPServer::GetEndPoint() const
  160. {
  161.     return mEndpoint;
  162. }
  163.  
  164. // ---------------------------------------------------------------------------
  165. //        • CreateServerWindow
  166. // ---------------------------------------------------------------------------
  167.  
  168. void
  169. CSimpleTCPServer::CreateServerWindow(
  170.     UInt32        inListenQueueSize,
  171.     UInt32        inPort)
  172. {
  173.     PP_PowerPlant::LCaption* theField;
  174.  
  175.     mWindow = PP_PowerPlant::LWindow::CreateWindow(PPob_WaitIngWindow, this);
  176.     
  177.     theField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pPort));
  178.     ThrowIfNil_ (theField);
  179.     theField->SetValue(inPort);
  180.     
  181.     theField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pAddress));
  182.     ThrowIfNil_ (theField);
  183.     
  184.     {
  185.         PP_PowerPlant::StDeleter<PP_PowerPlant::LInternetMapper>
  186.                             theMapper( PP_PowerPlant::UNetworkFactory::CreateInternetMapper() );
  187.  
  188.         PP_PowerPlant::StDeleter<PP_PowerPlant::LInternetAddress>
  189.                             tempAddress( theMapper->GetLocalAddress() );
  190.  
  191.         Str255    tempDescriptor;
  192.         theField->SetDescriptor(tempAddress->GetIPDescriptor(tempDescriptor));
  193.     }
  194.     
  195.     theField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pMaxConnection));
  196.     ThrowIfNil_ (theField);
  197.     theField->SetValue(inListenQueueSize);
  198.  
  199.     mConnectionCountField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pCurrConnection));
  200.     ThrowIfNil_ (mConnectionCountField);
  201.     mConnectionCountField->SetValue(mConnectionCount);
  202.  
  203.     mRejectionCountField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pRejectedConnection));
  204.     ThrowIfNil_ (mRejectionCountField);
  205.     mRejectionCountField->SetValue(mRejectionCount);
  206. }
  207.  
  208. // ---------------------------------------------------------------------------
  209. //        • AddToConnectionCount
  210. // ---------------------------------------------------------------------------
  211. void
  212. CSimpleTCPServer::AddToConnectionCount(short theCount)
  213. {
  214.     mConnectionCount += theCount;
  215.     mConnectionCountField->SetValue(mConnectionCount);
  216.     
  217.     //Start disconnect if we are quitting and the connection count is 0
  218.     if ((mConnectionCount == 0) && (mQuitWhenDone))
  219.         Disconnect();
  220. }
  221.  
  222. // ---------------------------------------------------------------------------
  223. //        • IncRejectionCount
  224. // ---------------------------------------------------------------------------
  225. void
  226. CSimpleTCPServer::IncRejectionCount()
  227. {
  228.     mRejectionCount++;
  229.     mRejectionCountField->SetValue(mRejectionCount);
  230. }
  231.  
  232. // ---------------------------------------------------------------------------
  233. //        • BindCompleted
  234. // ---------------------------------------------------------------------------
  235. //    We are now waiting for T_Listens... show the connection window
  236.  
  237. void
  238. CSimpleTCPServer::BindCompleted()
  239. {
  240.     mWindow->Show();
  241. }
  242.  
  243. // ---------------------------------------------------------------------------
  244. //        • BindFailed
  245. // ---------------------------------------------------------------------------
  246. //    Could not bind to the requested port.
  247.  
  248. void
  249. CSimpleTCPServer::BindFailed()
  250. {
  251.     SignalPStr_("\pBind Failed");
  252.     delete this;
  253. }
  254.  
  255. // ---------------------------------------------------------------------------
  256. //        • AllowSubRemoval
  257. // ---------------------------------------------------------------------------
  258. //    If user tries to close the main window, and we have ongoing connections,
  259. //    then block the action. If we don't have any connections then
  260. //    interpret this as a request to close the server.
  261.  
  262. Boolean
  263. CSimpleTCPServer::AllowSubRemoval(
  264.     LCommander *inSub)
  265. {
  266.     if ((inSub == mWindow) && (mConnectionCount > 0)) {
  267.         SysBeep(30);
  268.         return false;
  269.     }
  270.     else
  271.         return LSingleDoc::AllowSubRemoval(inSub);
  272. }
  273.  
  274. // ---------------------------------------------------------------------------
  275. //        • AttemptQuitSelf
  276. // ---------------------------------------------------------------------------
  277. //    Close our connection before quitting. We re-issue the quit command via
  278. //    the ServerThreadDied method once we are done.
  279.  
  280. Boolean
  281. CSimpleTCPServer::AttemptQuitSelf(
  282.     SInt32    inSaveOption)
  283. {
  284.     //This may seem odd, but...
  285.     //    subcommanders are called in order of creation so
  286.     //    this AttemptQuitSelf is called before any of the
  287.     //    responers it may have spawned.
  288.     //    Thus we return true here if mConnectionCount > 0
  289.     //    to give those a chance to get called too.
  290.     if (mConnectionCount > 0)
  291.         return true;
  292.     
  293.     if (mQuitWhenDone) {
  294.         return LCommander::AttemptQuitSelf(inSaveOption);
  295.     } else {
  296.         mQuitWhenDone = true;
  297.         mSaveOption = inSaveOption;
  298.         if (mConnectionCount == 0) {
  299.             Disconnect();
  300.         }
  301.         return false;
  302.     }
  303. }
  304.  
  305.